package org.example.dbcompare.service.data;

import cn.hutool.core.util.BooleanUtil;
import cn.hutool.db.Db;
import cn.hutool.db.ds.simple.SimpleDataSource;
import lombok.extern.slf4j.Slf4j;
import org.example.dbcompare.model.config.DataCompareConfig;
import org.example.dbcompare.model.config.DataCompareItem;
import org.example.dbcompare.model.context.DataCompareContext;
import org.example.dbcompare.model.result.CompareDataItem;
import org.example.dbcompare.model.result.CompareDataResult;

import java.util.ArrayList;
import java.util.List;

/**
 * 数据对比服务
 *
 * @author wuyong
 * @date 2025/10/22
 */
@Slf4j
public class DataCompareService {

    /**
     * 对比指定表的数据是否相等
     *
     * @param context   数据对比上下文
     * @return 数据对比结果
     */
    public CompareDataResult compareData(DataCompareContext context, DataCompareConfig dataCompareConfig) {
        CompareDataResult result = new CompareDataResult();
        List<CompareDataItem> items = new ArrayList<>();

        SimpleDataSource sourceDataSource = new SimpleDataSource(
                context.getSourceDb().getUrl(),
                context.getSourceDb().getUsername(),
                context.getSourceDb().getPassword()
        );
        SimpleDataSource targetDataSource = new SimpleDataSource(
                context.getTargetDb().getUrl(),
                context.getTargetDb().getUsername(),
                context.getTargetDb().getPassword()
        );

        if (dataCompareConfig == null || dataCompareConfig.getDataCompareItems() == null) {
            result.compareDataItems = items;
            return result;
        }

        AddCompare addCompare = new AddCompare(sourceDataSource,targetDataSource);
        UpdateCompare updateCompare = new UpdateCompare(sourceDataSource,targetDataSource);
        for (DataCompareItem cfgItem : dataCompareConfig.getDataCompareItems()) {
            CompareDataItem item = compareSingleTable(sourceDataSource, targetDataSource, cfgItem);
            try {
                if(BooleanUtil.isTrue(cfgItem.getCompareAndSyncAdded())) {
                    addCompare.compare(cfgItem, item);
                }
                if(BooleanUtil.isTrue(cfgItem.getCompareAndSyncModified())) {
                    updateCompare.compare(cfgItem, item);
                }
            } catch (Exception e) {
                log.error("计算插入差异失败, 表 {}: {}", cfgItem.getTableName(), e.getMessage(), e);
            }
            items.add(item);
        }

        result.compareDataItems = items;
        return result;
    }

    /**
     * 对比单个表的数据（基于COUNT快速判断）
     */
    private CompareDataItem compareSingleTable(SimpleDataSource sourceDataSource,
                                               SimpleDataSource targetDataSource,
                                               DataCompareItem cfgItem) {
        long start = System.currentTimeMillis();
        CompareDataItem.CompareDataItemBuilder builder = CompareDataItem.builder()
                .tableName(cfgItem.getTableName())
                .startTime(start);
        try {
            String where = cfgItem.getWhereClause();
            String table = cfgItem.getTableName();
            String srcSql = "SELECT COUNT(1) FROM " + table + (where != null && !where.isEmpty() ? " WHERE " + where : "");
            String tgtSql = srcSql;

            long srcCount = Db.use(sourceDataSource).queryNumber(srcSql).longValue();
            long tgtCount = Db.use(targetDataSource).queryNumber(tgtSql).longValue();

            boolean equal = srcCount == tgtCount;
            builder.sourceRecordCount(srcCount)
                    .targetRecordCount(tgtCount)
                    .mismatchRowCount(Math.abs(srcCount - tgtCount))
                    .isEqual(equal);
        } catch (Exception ex) {
            log.error("对比表 {} 时出错: {}", cfgItem.getTableName(), ex.getMessage(), ex);
            builder.isEqual(false).errorMessage(ex.getMessage());
        } finally {
            builder.endTime(System.currentTimeMillis());
        }
        return builder.build();
    }
}
